from helpFunc import *
import socket,select
from streambase import streamBase

class UStreamServer(streamBase):
    def __init__(self,portNum,salt,rate,pushAhead,packLimit,debug):
        streamBase.__init__(self,rate,pushAhead,packLimit,True)
        self.sockMap = {}
        self.ip = con_listenIp
        self.debug = debug
        self.portList = self.iniListenPort(portNum)
        self.salt = salt
        
        
    def iniListenPort(self,n):
        retL = []
        if self.debug:
            for i in range(50000,50000+n):
                sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
                sock.bind((self.ip, i))
                sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)     
                retL.append(int(sock.getsockname()[1]))
                self.sockMap[sock] = {}   
            return retL 
        for i in range(n):
            sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
            sock.bind((self.ip, 0))
            sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)     
            retL.append(int(sock.getsockname()[1]))
            self.sockMap[sock] = {}
        return retL        
        
    def deal_rec(self,l):
        re = []
        reSocks = []
        for one in l:
            if one == self.outSo:
                continue
            data, addr = one.recvfrom(recLen)
            uuid ,ss = checkPackValid_server(data,self.salt)
            if not uuid :
                continue
            addPackSta(self.maxRec,len(data))
            self.sockMap[one]['uuid'] = uuid
            self.sockMap[one]['addr'] = addr
            re.append(ss)
            reSocks.append(one)
        return re,reSocks
         
    def  sendData(self,re,l):
        co = -1
        for sock in l:
            co += 1
            data = makePack_server(re[co], self.sockMap[sock]['uuid'], self.salt)
            sock.sendto(data,self.sockMap[sock]['addr'])    
            addPackSta(self.maxSendL,len(data))         
            
    def doWork(self):
        self.makeOutSo()
        while True:
            if getRunningTime()-self.updatedTime>con_closeTime:
                import os
                os._exit(0)    
            rl = list(self.sockMap.keys())            
            if len(self.writeBuffer)<con_streamBufferSize:
                rl.append(self.outSo)
                
            wl = []
            if self.readBuffer:
                wl.append(self.outSo)
                
            r = select.select(rl,wl,[],1)

            if r[1]:
                n = self.outSo.send(self.readBuffer)
                self.readBuffer = self.readBuffer[n:]
                
            if r[0]==[]:
                continue                
            if self.outSo in r[0]:
                self.writeBuffer += self.outSo.recv(con_streamBufferSize-len(self.writeBuffer))
                
            re,reSocks = self.deal_rec(r[0])
            self.deal_data_back(re)     
            self.read()
            self.write()
            re = self.get_data_to_send(len(reSocks)) 
            self.sendData(re,reSocks) 
            if getRunningTime()-self.staTime>1:
                self.staTime = getRunningTime()  
                self.rRaw = self.wRaw = self.rNet = self.wNet = 0
                self.totalRec = self.blankRec = self.totalSend = self.blankSend = self.statusSend = self.statusRev = 0    
                clearPackSta(self.maxSendL)          
                clearPackSta(self.maxRec)          
                clearPackSta(self.peerMaxRec)          
                clearPackSta(self.peerMaxSend)            
                print (len(self.maxSendL),len(self.maxRec),len(self.peerMaxSend),len(self.peerMaxRec))
                
if __name__ == "__main__":
    import threading
    serverIp = con_serverIp
    rate = con_minRate
    pushAhead = con_pushAhead
    packLimit = con_packLimit
    salt = b'salt'
    
    u = UStreamServer(maxPortNum,salt,rate,pushAhead,packLimit,True)
    t = threading.Thread(target=u.doWork)
    t.setDaemon(True)
    t.start()
    while True:
        try:
            so = socket.socket()
            add = ('127.0.0.1',u.listenPort)
            so.connect(add)    
            break
        except:
            pass
    print ('server starts')
    import testStream
    #testStream.doTest(so)
    co =0;
    t = time.time()
    while True:
        a = so.recv(100000)
        co+=len(a)
        if time.time()-t >1:
            t = time.time()
            print (co,t)
      